//! Appender Trait 单元测试

mod common;

use common::TestAppender;
use log4r::{Appender, Level, Log4rError, LogEvent};
use std::sync::{Arc, Mutex};

/// [P0] 测试 TestAppender 实现 Appender trait
#[test]
fn test_test_appender_implements_appender() {
    let appender = TestAppender::new();
    let event = LogEvent::new(Level::Info, "test", "测试消息");

    assert!(appender.write(&event).is_ok());
    assert!(appender.flush().is_ok());
    assert!(appender.close().is_ok());
}

/// [P0] 测试 Appender write 方法
#[test]
fn test_appender_write() {
    let appender = TestAppender::new();
    let event = LogEvent::new(Level::Error, "error_module", "错误消息");

    let result = appender.write(&event);
    assert!(result.is_ok());
    assert_eq!(appender.count(), 1);

    let events = appender.get_events();
    assert_eq!(events[0].level, Level::Error);
    assert_eq!(events[0].message, "错误消息");
}

/// [P0] 测试 Appender 多次写入
#[test]
fn test_appender_multiple_writes() {
    let appender = TestAppender::new();

    for i in 0..5 {
        let event = LogEvent::new(Level::Info, "test", format!("消息 {}", i));
        let _ = appender.write(&event);
    }

    assert_eq!(appender.count(), 5);
}

/// [P1] 测试 Appender flush 方法
#[test]
fn test_appender_flush() {
    let appender = TestAppender::new();
    assert!(appender.flush().is_ok());
}

/// [P1] 测试 Appender close 方法
#[test]
fn test_appender_close() {
    let appender = TestAppender::new();
    assert!(appender.close().is_ok());
}

/// [P1] 测试 Appender 是 Send + Sync
#[test]
fn test_appender_send_sync() {
    let appender = TestAppender::new();
    fn assert_send_sync<T: Send + Sync>(_: &T) {}
    assert_send_sync(&appender);
}

/// [P1] 测试 Appender 可以作为 trait 对象
#[test]
fn test_appender_as_trait_object() {
    let appender = TestAppender::new();
    let boxed: Box<dyn Appender> = Box::new(appender);
    let event = LogEvent::new(Level::Info, "test", "trait object test");
    assert!(boxed.write(&event).is_ok());
}

/// [P1] 测试 Appender 线程安全写入
#[test]
fn test_appender_thread_safe_write() {
    let appender = Arc::new(TestAppender::new());
    let mut handles = vec![];

    for i in 0..10 {
        let appender_clone: Arc<TestAppender> = Arc::clone(&appender);
        let handle = std::thread::spawn(move || {
            let event = LogEvent::new(Level::Info, "thread_test", format!("线程 {} 消息", i));
            appender_clone.write(&event)
        });
        handles.push(handle);
    }

    for handle in handles {
        assert!(handle.join().is_ok());
    }

    assert_eq!(appender.count(), 10);
}

/// [P2] 测试自定义 Appender 实现
#[test]
fn test_custom_appender_implementation() {
    struct CountingAppender {
        count: Arc<Mutex<usize>>,
    }

    impl Appender for CountingAppender {
        fn write(&self, _event: &LogEvent) -> Result<(), Log4rError> {
            if let Ok(mut count) = self.count.lock() {
                *count += 1;
            }
            Ok(())
        }

        fn flush(&self) -> Result<(), Log4rError> {
            Ok(())
        }

        fn close(&self) -> Result<(), Log4rError> {
            Ok(())
        }
    }

    let count = Arc::new(Mutex::new(0));
    let appender = CountingAppender {
        count: Arc::clone(&count),
    };

    let event = LogEvent::new(Level::Info, "test", "test");
    let _ = appender.write(&event);
    let _ = appender.write(&event);

    assert_eq!(*count.lock().unwrap(), 2);
}

/// [P2] 测试 Appender 错误返回
#[test]
fn test_appender_error_return() {
    struct FailingAppender;

    impl Appender for FailingAppender {
        fn write(&self, _event: &LogEvent) -> Result<(), Log4rError> {
            Err(Log4rError::AppenderError {
                name: "FailingAppender".to_string(),
                cause: "总是失败".to_string(),
            })
        }

        fn flush(&self) -> Result<(), Log4rError> {
            Err(Log4rError::AppenderError {
                name: "FailingAppender".to_string(),
                cause: "刷新失败".to_string(),
            })
        }

        fn close(&self) -> Result<(), Log4rError> {
            Err(Log4rError::AppenderError {
                name: "FailingAppender".to_string(),
                cause: "关闭失败".to_string(),
            })
        }
    }

    let appender = FailingAppender;
    let event = LogEvent::new(Level::Info, "test", "test");

    assert!(appender.write(&event).is_err());
    assert!(appender.flush().is_err());
    assert!(appender.close().is_err());
}
